'''
Created on Mar 8, 2012

@author: david
'''
from pspy.csv import ProxyRunner
from pspy import Notification
import logging

class BulkLoader(object):
    """
    Load model instances with rows from a csv file
    """
    NUMERICAL_TYPES = ['IntegerProperty','BooleanProperty','FloatProperty','RatingProperty']
    
    def __init__(self, fileLikeObject, modelType):
        """
        Constructor saves file like object and model name.
        """
        # save params
        self._file = fileLikeObject
        self._model = modelType
        
        # parse out package for model
        imp = ".".join(modelType.split('.')[:-1])
        logging.debug("~~ Importing module: %s" % imp)
        
        # import module
        self.mod = __import__(imp)
    
    def run(self):
        """
        Create proxy runner and run it.
        """
        try:
            # proxy runner for file data uses
            # internal method
            pr = ProxyRunner(self._file,self.row2model)
            pr.run()
        except Exception,ex:
            n = Notification("BulkLoader Error")
            n.setException(ex)
        
    def row2model(self,data):
        """
        Do the work.
        """
        # create the model object
        s = '%s()' % self._model.replace('app','self.mod')        
        logging.debug("~~ Eval'ing: %s" % s)
        m = eval(s)
        
        # assign all the attributes
        for k in data.keys():
            try:
                # get the model attribute name
                n = "m.%s" % k
                
                # and the value
                d = self._format(m, k, data['%s' % k])
                logging.debug("~~ Setting: %s = %s" % (n,d))
                
                # and do the set
                exec("%s = %s" % (n,d))
            except Exception,ex:
                n = Notification("BulkLoader Error")
                n.setException(ex)
            
        # and save model to the store    
        m.put()
        
    def _format(self,model,nam,value):
        "To quote or not to quote, that is the question"       
        # get attribute/property listings
        p = model.properties()
        
        # check for numerical values
        rslt = "'%s'" % value
        if str(p[nam]).split('.')[-1].split(' ')[0] in self.NUMERICAL_TYPES:
            rslt = "%s" % value
        
        # return result string
        return rslt
